from fastapi import APIRouter, Depends, Response
from fastapi.responses import PlainTextResponse
import aiohttp
import asyncio
from sqlalchemy.orm import Session
from urllib.parse import urlparse
from io import StringIO
from typing import Dict, List, Optional
import re

from app.crud import get_exporters
from app.database import get_db

router = APIRouter()

async def fetch_metrics(url: str, timeout: int = 5) -> Optional[str]:
    """获取指标数据"""
    try:
        timeout = aiohttp.ClientTimeout(total=timeout)
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.get(url) as response:
                if response.status == 200:
                    return await response.text()

    except Exception as e:
        return None

def format_metrics(metrics: str, exporter_info: Dict) -> str:
    """格式化指标数据，添加完整的采集点地址信息"""
    if not metrics:
        return ""
    
    buffer = StringIO()
    # 构建完整标签集合
    labels = {
        "exporter_address": f"{exporter_info['host']}:{exporter_info['port']}",
        "exporter_name": exporter_info.get("name", ""),
        "exporter_type": exporter_info.get("type", "unknown")
    }
    # 过滤空值标签
    labels = {k: v for k, v in labels.items() if v}
    label_str = ",".join(f'{k}="{v}"' for k, v in labels.items())
    
    for line in metrics.splitlines():
        
        if not line or line.startswith("#"):
            buffer.write(f"{line}\n")
            continue
        
        # 提取指标名和可能存在的已有标签
        metric_parts = line.rsplit(' ', 1)
        if len(metric_parts) < 2:
            
            buffer.write(f"{line}\n")
            continue
            
        metric_name = metric_parts[0]
        metric_value = metric_parts[-1]
        # 处理已有标签的情况
        if "{" in metric_name and "}" in metric_name:
            # 在已有标签后追加
            
            new_metric_name = re.sub(r'}(.*?)$', f',{label_str}}}\\1', metric_name)
            
        else:
            # 无标签则新建标签部分
            new_metric_name = f"{metric_name}{{{label_str}}}"
        
        # 重建指标行
        new_line = f"{new_metric_name} {metric_value}"
        buffer.write(f"{new_line}\n")
    
    return buffer.getvalue().strip()

@router.get("/metrics", response_class=PlainTextResponse)
async def metrics_endpoint(db: Session = Depends(get_db)):
    """聚合指标端点，为每个指标添加采集点信息"""
    exporters = get_exporters(db)
    if not exporters:
        return Response(content="", status_code=204)
    
    tasks = []
    exporter_infos = []
    for exporter in exporters:
        if exporter.enabled:
            url = f"http://{exporter.host}:{exporter.port}{exporter.path}"
            tasks.append(fetch_metrics(url))
            exporter_infos.append({
                "host": exporter.host,
                "port": exporter.port,
                "path": exporter.path,
                "name": getattr(exporter, "name", ""),
                "type": getattr(exporter, "type", "unknown")
            })
    
    results = await asyncio.gather(*tasks)
    
    output = StringIO()
    for info, result in zip(exporter_infos, results):
        if result:
            formatted = format_metrics(result, info)
            if formatted:
                output.write(f"# 采集点: {info['host']}\n")
                output.write(formatted)
                output.write("\n\n")
    
    content = output.getvalue().strip()
    return PlainTextResponse(content) if content else Response(content="", status_code=204)